package com.example.chesswithnet.Entity;

import javafx.geometry.Point2D;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;

import java.util.Map;

public class Chess {

    private String url;
    private Double x;
    private Double y;
    //简化坐标
    private Point2D p;
    private int player; //0：红色，1：黑色
    private String suffix = ".png";

//    private ChineseChess.chessController chessController = new chessController();

    /**
     * 绘制棋子
     * @param gc
     */
    public void draw(GraphicsContext gc){
//        System.out.println("img1/"+url+String.valueOf(player)+suffix);
        Image image = new Image(String.valueOf(getClass().getResource("../img1/"+url+String.valueOf(player)+suffix)));
        gc.drawImage(image,x,y,30,30);
    }

    /**
     * 反转棋子
     */
    public void reservePoint(){
        double x1 = 8 - p.getX();
        double y1 = 9 - p.getY();
        setX(5 + 40 * x1);
        setY(5 + 40 * y1);
        setP(new Point2D(x1,y1));
    }

    /**
     * 判断棋子是在棋盘上面还是下面
     * @return
     */
    public boolean isUporDown(){
        if(p.getY() < 5)  return true; //上边
        return false;  //下边
    }

    /**
     * 判断是否在王宫范围内
     */
    public boolean isHome(Point2D p){
//        System.out.println(url);
        if(isUporDown()){
            if(p.getX() < 3 || p.getX() >5)
                return false;
            else if(p.getY() < 0 || p.getY() > 2)
                return false;
//            else if(url.equalsIgnoreCase("boss"))
//                return true;
        }else {
            if(p.getX() < 3 || p.getX() >5)
                return false;
            else if(p.getY() < 7 || p.getY() > 9)
                return false;
//            else if(url.equalsIgnoreCase("boss"))
//                return true;
        }
        return true;
    }

    /**
     * 判断棋子可否移动
     * @param p 目标位置
     * @param map 棋子集合
     * @return
     */
    public boolean isAbleMoved(Point2D p, Map<Point2D,Chess> map){
//        if (!eatChess(p,map)) return false;
        if(url.equalsIgnoreCase("boss"))
            return isHome(p) && LineOneMove(p);
        else if(url.equalsIgnoreCase("shi"))
            return isHome(p) && slashMove(p);
        else if(url.equalsIgnoreCase("ma"))
            return RiziMove(p) && !isBiejiao(p,map);
        else if(url.equalsIgnoreCase("xiang"))
            if(isUporDown())
                return TianziMove(p) && !isBiejiao(p,map) && p.getY() < 5;  //p.getY() < 5表示上边不能过河
            else
                return TianziMove(p) && !isBiejiao(p,map) &&  p.getY() > 4; //p.getY() > 表示下边不能过河
        else if(url.equalsIgnoreCase("bing"))
            return BingMove(p) && LineOneMove(p);
        else if(url.equalsIgnoreCase("che"))
            return HaveChess(p,map) && LineMove(p);
        else if(url.equalsIgnoreCase("pao"))
            return HaveChess(p,map) && LineMove(p);
        return true;
    }

    /**
     * 棋子吃子规则
     * @param p
     * @param map
     * @return
     */
    public boolean eatChess(Point2D p,Map<Point2D,Chess> map){
        if(map.get(p) == null) return true;   //目标位置没有棋子就移动
        String name = getUrl();
        Chess chess = map.get(p);
        switch (name){
            case "boss":  //可以吃除兵卒以外的棋子
                if(chess.url == "bing" && chess.getPlayer() != getPlayer()) return false;
                break;
            case "shi":  //可以吃除将帅以外的棋子
                if(chess.url == "boss" && chess.getPlayer() != getPlayer()) return false;
                break;
            case "xiang":  //可以吃除士、帅以外的棋子
                if((chess.url == "shi" || chess.url == "boss") && chess.getPlayer() != getPlayer()) return false;
                break;
            case "che":  //可以吃除象、士、将帅以外的棋子
                if((chess.url == "xiang" || chess.url == "shi" || chess.url == "boss") && chess.getPlayer() != getPlayer()) return false;
                break;
            case "ma":  //可以吃马、炮、兵
                if(!(chess.url == "ma" || chess.url == "pao" || chess.url == "bing") && chess.getPlayer() != getPlayer()) return false;
                break;
            case "pao":  //可以吃任何棋子，但是中间必须隔着一个棋子
                break;
            case "bing":  //只能吃对方的将、兵（卒）
                if(!(chess.url == "boss" || chess.url == "bing") && chess.getPlayer() != getPlayer()) return false;
                break;
        }
        return true;
    }

    /**
     * 判断移动路上是否有棋子
     * @param p
     * @param map
     * @return
     */
    public boolean HaveChess(Point2D p,Map map){
        int m = 0, n = 0;
        Integer count = 0;  //路上棋子的个数
        //竖向移动
        if(p.getX() == getP().getX()) {
            m = (int)p.getY();
            n = (int)getP().getY();
            if (m > n) {
                for (int i = n + 1; i < m; i++)
                    if (map.get(new Point2D(p.getX(), i)) != null) count++;
            }else
                for (int i = n - 1; i > m; i--)
                    if (map.get(new Point2D(p.getX(), i)) != null) count++;
        }
        //横向移动
        else if (p.getY() == getP().getY()) {
            m = (int) p.getX();
            n = (int) getP().getX();
            if (m > n) {
                for (int i = n + 1; i < m; i++)
                    if (map.get(new Point2D(i, p.getY())) != null) count++;
            } else
                for (int i = n - 1; i > m; i--)
                    if (map.get(new Point2D(i, p.getY())) != null) count++;
        }

        System.out.println("count"+count);
        if(getUrl().equalsIgnoreCase("pao") && count == 1)  //炮吃子
            return paoEatChess(count,p,map);
        else if(count > 0) return false;
//        else if(map.get(p) != null) return false;
        return true;
    }

    /**
     * 炮吃子规则
     * @param count  路上的棋子
     * @param p
     * @param map
     * @return
     */
    public boolean paoEatChess(Integer count,Point2D p,Map<Point2D,Chess> map){
        if(map.get(p) != null && count == 1) return true;
        return false;
    }

    /**
     * 直线移动
     * @param p
     * @return
     */
    public boolean LineMove(Point2D p){
        if(p.getX() == getP().getX() && p.getY() != getP().getY()
                || p.getY() == getP().getY() && p.getX() != getP().getX())
            return true;
        return false;
    }

    /**
     * 兵移动规则
     * @param p 目标位置
     * @return
     */
    public boolean BingMove(Point2D p){
        if (getPlayer() == 0) {  //上边
            if (p.getY() < getP().getY()) return false; // 不能后退
            else if (getP().getY() < 5)   //没过河
                if (p.getX() != getP().getX()) return false;  //不能左右移动
        }else {  //下边
            if (p.getY() > getP().getY()) return false; // 不能后退
            else if (getP().getY() > 4)   //没过河
                if (p.getX() != getP().getX()) return false;  //不能左右移动
        }
        return true;
    }

    /**
     * 直线移动一格
     * @param point2D 目标位置
     * @return
     */
    public boolean LineOneMove(Point2D point2D) {
        if (getP().getX() == point2D.getX()) {
            if (Math.abs(point2D.getY() - getP().getY()) == 1)
                return true;
        } else if (getP().getY() == point2D.getY()) {
            if (Math.abs(point2D.getX() - getP().getX()) == 1)
                return true;
        } else
            return false;
        return false;
    }

    /**
     * 日字移动
     * @param p 目标位置
     * @return
     */
    public boolean RiziMove(Point2D p) {
        if (Math.abs(getP().getX() - p.getX()) == 1 && Math.abs(getP().getY() - p.getY()) == 2
            || Math.abs(getP().getX() - p.getX()) == 2 && Math.abs(getP().getY() - p.getY()) == 1)
            return true;
        return false;
    }

    /**
     * 田字移动
     * @return
     */
    public boolean TianziMove(Point2D p) {
        if (Math.abs(getP().getX() - p.getX()) == 2 && Math.abs(getP().getY() - p.getY()) == 2)
            return true;
        return false;
    }

    /**
     * 判断是否蹩脚
     * @param p  目标位置
     * @return  true:被蹩脚  false:没有蹩脚
     */
    public boolean isBiejiao(Point2D p,Map<Point2D,Chess> map){
        Point2D point2D = null;  //中心点
        double x=0.0,y = 0.0;
        if(getUrl().equalsIgnoreCase("xiang")){
            x = (getP().getX() + p.getX()) / 2;
            y = (getP().getY() + p.getY()) / 2;
        }else if(getUrl().equalsIgnoreCase("ma")){
            if(Math.abs(p.getX() - getP().getX()) == 2){
                x = (int)((getP().getX() + p.getX()) / 2);
                y = getP().getY();
            }else if(Math.abs(p.getX() - getP().getX()) == 1){
                x = getP().getX();
                y = (int)((getP().getY() + p.getY()) / 2);
            }
        }
        point2D = new Point2D(x,y);
        if(map.get(point2D) == null) return false;
        return true;
    }

    /**
     * 正斜线移动
     * @param p  目标位置
     * @return
     */
    public boolean slashMove(Point2D p){
            if(Math.abs(getP().getY()-p.getY()) == 1 && Math.abs(getP().getX()-p.getX()) == 1)
                return true;
        return false;
    }

    public void setPointXY(Point2D p,Double x,Double y){
        this.p = p;
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "Chess{" +
                "url='" + url + '\'' +
                ", x=" + x +
                ", y=" + y +
                ", p=" + p +
                ", player=" + player +
                '}';
    }

    public Chess(String url, Point2D p, int player) {
        this.url = url;
        this.p = p;
        this.player = player;
    }

    public Chess(String url, Double x, Double y, Point2D p, int player) {
        this.url = url;
        this.x = x;
        this.y = y;
        this.p = p;
        this.player = player;
    }

    public int getPlayer() {
        return player;
    }

    public void setPlayer(int player) {
        this.player = player;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Double getX() {
        return x;
    }

    public void setX(Double x) {
        this.x = x;
    }

    public Double getY() {
        return y;
    }

    public void setY(Double y) {
        this.y = y;
    }

    public Point2D getP() {
        return p;
    }

    public void setP(Point2D p) {
        this.p = p;
    }
}
